package cn.xawl.gulimall.cart.service.impl;

import cn.xawl.common.utils.R;
import cn.xawl.gulimall.cart.feign.ProductFeignService;
import cn.xawl.gulimall.cart.interceptor.CartTempUserInterceptor;
import cn.xawl.gulimall.cart.service.CartService;
import cn.xawl.gulimall.cart.vo.Cart;
import cn.xawl.gulimall.cart.vo.CartItem;
import cn.xawl.gulimall.cart.vo.SkuInfoVo;
import cn.xawl.gulimall.cart.vo.UserInfoTo;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

/**
 * @author lh
 * @create 2020-11-02 15:53
 **/
@Service
public class CartServiceImpl implements CartService {

    public final static String USER_CART_PREFIX = "gulumall:cart:";

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private ProductFeignService productFeignService;

    @Override
    public void addToCart(Long skuId, Integer num) {
        //获取不同状态用户的购物车操作类
        BoundHashOperations<String, String, String> cartRedisOps = getCartRedisOps();
        //判断当前用户是否添加过当前物品到购物车
        String jsonCart = cartRedisOps.get(String.valueOf(skuId));
        //将json字符串转为对象
        CartItem redisItem = JSON.parseObject(jsonCart, CartItem.class);

        if (redisItem != null) {
            //当前用户已经添加过该商品，直接修改数量即可
            redisItem.setCount(redisItem.getCount() + num);
            cartRedisOps.put(skuId.toString(), JSON.toJSONString(redisItem));
        } else {
            CartItem cartItem = new CartItem();
            //当前用户的购物车中没有相同的物品。将该商品的完整信息存入redis
            cartItem.setCount(num);
            cartItem.setSkuId(skuId);
            //其他信息需要通过远程商品服务根据skuId查询。
            //TODO 使用CompletableFuture管理远程调用
            R info = productFeignService.info(skuId);
            if ((int) info.get("code") == 0) {
                //远程服务调用成功
                SkuInfoVo skuInfo = info.getData(SkuInfoVo.class, "skuInfo");
                cartItem.setImage(skuInfo.getSkuDefaultImg());
                cartItem.setTitle(skuInfo.getSkuTitle());
                cartItem.setUnitPrice(skuInfo.getPrice());
            }
            //调用商品服务，查询skuId对应的销售属性
            R r = productFeignService.skuSaleAttrs(skuId);
            if ((int) info.get("code") == 0) {
                List<String> saleAttrs = r.getData(new TypeReference<List<String>>() {
                });
                cartItem.setSaleAttr(saleAttrs);
            }
            cartRedisOps.put(skuId.toString(), JSON.toJSONString(cartItem)); //将购物车数据保存为json字符串
        }
    }

    @Override
    public CartItem getCartItems(Long skuId) {
        BoundHashOperations<String, String, String> cartRedisOps = getCartRedisOps();
        String s = cartRedisOps.get(String.valueOf(skuId));

        return JSON.parseObject(s, CartItem.class);
    }

    @Override
    public Cart userCart() {
        UserInfoTo userInfoTo = CartTempUserInterceptor.threadLocal.get();
        Cart cart = new Cart();
        String tempCartKey = USER_CART_PREFIX + userInfoTo.getUserKey();
        List<CartItem> tempUserCart = getUserCartItems(tempCartKey);
        if (userInfoTo.getUserId() == null) {
            //当前未登录
            //将所有临时用户的购物车信息查询后返回
            cart.setItems(tempUserCart);
        } else {
            //当前已登录
            //先查出临时用户的购物车，然后再将登录用户的购物车合并
            String loginUserKey = USER_CART_PREFIX + userInfoTo.getUserId();
            if (!CollectionUtils.isEmpty(tempUserCart)) {
                for (CartItem cartItem : tempUserCart) {
                    addToCart(cartItem.getSkuId(), cartItem.getCount());
                }
                clearTempCart(tempCartKey);
            }
            List<CartItem> loginUserCarts = getUserCartItems(loginUserKey);
            cart.setItems(loginUserCarts);
        }
        return cart;
    }

    @Override
    public void clearTempCart(String tempUserKey) {
        redisTemplate.delete(tempUserKey);
    }

    @Override
    public void cartItemChange(String skuId, Integer change) {
        CartItem cartItem = getCartItems(Long.parseLong(skuId));
        BoundHashOperations<String, String, String> cartRedisOps = getCartRedisOps();
        if (change == null) {
            getCartRedisOps().delete(skuId);
            return;
        }
        if (change < 0) {
            if (change == -1) {
                cartItem.setChecked(false);
            }
            if (change == -2) {
                cartItem.setChecked(true);
            }
        }
        if (change >= 0) {
            cartItem.setCount(change);
        }
        cartRedisOps.put(skuId, JSON.toJSONString(cartItem));
    }

    private List<CartItem> getUserCartItems(String cartKey) {
        BoundHashOperations<String, String, String> tempCartOps = redisTemplate.boundHashOps(cartKey);
        List<String> values = tempCartOps.values();
        if (!CollectionUtils.isEmpty(values)) {
            return values.stream().map(item -> JSON.parseObject(item, CartItem.class)).collect(Collectors.toList());
        }
        return null;
    }

    private BoundHashOperations<String, String, String> getCartRedisOps() {
        //获取当前线程下保存的用户信息
        UserInfoTo userInfoTo = CartTempUserInterceptor.threadLocal.get();
        if (userInfoTo.getUserId() == null) {
            //当前未登录
            //根据cookie中存储的user-key来存储购物车信息
            return redisTemplate.boundHashOps(USER_CART_PREFIX + userInfoTo.getUserKey());
        } else {
            //当前已登录  根据用户id存储购物车信息
            return redisTemplate.boundHashOps(USER_CART_PREFIX + userInfoTo.getUserId());
        }
    }
}
